﻿using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing;

namespace Miso
{
    class MisoApplicationContext : ApplicationContext
    {
        // System API used to set screensaver state
        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool SystemParametersInfo(uint uiAction, bool uiParam, uint pvParam, uint init);

        private const uint SPI_SETSCREENSAVEACTIVE = 0x0011;

        // System API used to get screen saver state
        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool SystemParametersInfo(uint uiAction, uint uiParam, out bool pvParam, uint init);

        private const uint SPI_GETSCREENSAVEACTIVE = 0x0010;

        // System API used to prevent the display sleeping
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);

        public enum EXECUTION_STATE : uint
        {
            ES_SYSTEM_REQUIRED = 0x00000001,
            ES_DISPLAY_REQUIRED = 0x00000002,
            // Legacy flag, should not be used.
            // ES_USER_PRESENT   = 0x00000004,
            ES_CONTINUOUS = 0x80000000,
        }

        // State variable used to toggle between screensaver/power-saving enabled or disabled.
        private bool screensaverActive;

        // UI components
        private System.ComponentModel.IContainer components;
        private System.Windows.Forms.NotifyIcon trayIcon;
        private System.Windows.Forms.ContextMenu contextMenu;
        private System.Windows.Forms.MenuItem exitContextMenuItem;
        private System.Windows.Forms.MenuItem toggleContextMenuItem;

        public MisoApplicationContext()
        {
            // create the notify icon and its associated context menu
            InitializeContext();

            UpdateStatus();
        }

        public void InitializeContext()
        {
            this.components = new System.ComponentModel.Container();
            this.trayIcon = new System.Windows.Forms.NotifyIcon(this.components);
            this.contextMenu = new System.Windows.Forms.ContextMenu();
            this.exitContextMenuItem = new System.Windows.Forms.MenuItem();
            this.toggleContextMenuItem = new System.Windows.Forms.MenuItem();

            // 
            // trayIcon
            // 
            this.trayIcon.ContextMenu = this.contextMenu;
            this.trayIcon.MouseClick += new System.Windows.Forms.MouseEventHandler(this.trayIcon_MouseClick);
            this.trayIcon.Visible = true;

            // 
            // contextMenu
            // 
            this.contextMenu.MenuItems.AddRange(new MenuItem[] { toggleContextMenuItem, exitContextMenuItem });

            // 
            // toggleContextMenuItem
            // 
            this.toggleContextMenuItem.Index = 0;
            this.toggleContextMenuItem.Text = "&Toggle";
            this.toggleContextMenuItem.Click += new System.EventHandler(this.toggleScreensaverState); 

            // 
            // exitContextMenuItem
            // 
            this.exitContextMenuItem.Index = 1;
            this.exitContextMenuItem.Text = "&Exit";
            this.exitContextMenuItem.Click += new System.EventHandler(this.exitContextMenuItem_Click);  
        }


        /// <summary>
        /// When the application context is disposed, dispose things like the notify icon.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
        }

        
        private void exitContextMenuItem_Click(object sender, EventArgs e)
        {
            AllowMonitorPowerdown();
            ExitThread();
        }


        private void trayIcon_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                toggleScreensaverState(sender, e);
            }
        }


        private void toggleScreensaverState(object sender, EventArgs e)
        {
            screensaverActive = !screensaverActive;
            if (screensaverActive) AllowMonitorPowerdown(); else PreventMonitorPowerdown();
            UpdateStatus();
        }


        private void PreventMonitorPowerdown()
        {
            SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, false, 0, 0);
            SetThreadExecutionState(EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
        }


        private void AllowMonitorPowerdown()
        {
            SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, true, 0, 0);
            SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);
        }


        private void UpdateStatus()
        {
            SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, out screensaverActive, 0);

            trayIcon.Icon = new Icon(GetType(), screensaverActive ? "empty.ico" : "full.ico");
            this.trayIcon.Text = "Screensaver and Power-Saving " + (screensaverActive ? "Enabled" : "Disabled");

            this.toggleContextMenuItem.Text = (screensaverActive ? "Disable" : "Enable") + " Display Power-Saving";
        }
    }
}
